package io.jee.medusa.orm.pager.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import io.jee.medusa.orm.pager.OperationType;
import io.jee.medusa.orm.pager.RelationType;
import io.jee.medusa.orm.pager.annotation.Condition;

public class HQLUtils {
	
	public static String[] toHql(Object object, final Map<String, Object> params) {
		String[] hqls = new String[2];
		Assert.notNull(object, "条件对象不能为Null:"+object.getClass().getName());
		StringBuffer from = new StringBuffer();
		StringBuffer hql = new StringBuffer();
		Method[] methods = object.getClass().getMethods();
		boolean hasFirst = false;
		for (Method method : methods) {
			Condition condition;
			if((condition = method.getAnnotation(Condition.class))!=null){
				String name = condition.fieldName();
				if(!StringUtils.hasText(name)){
					name = method.getName();
					if(name.startsWith("get")){
						name = name.substring(3, 4).toLowerCase()+name.substring(4);
					}else if(name.startsWith("is")){
						name = name.substring(2, 3).toLowerCase()+name.substring(3);
					}
				}
				RelationType relationType = condition.relation();
				OperationType operationType = condition.operation();
				Object result = null;
				try {
					result = method.invoke(object, new Object[]{});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					throw new IllegalArgumentException("确定注解打在get方法上的？确定get方法没有形参？");
				}
				if(result instanceof String){
					if("".equals(result)){
						result = null;
					}
				}
				if(result != null || condition.hasNull()){
					String hqlTemp = "";
					//将条件组单独列出来递归下，且不加入参数值
					if(operationType == OperationType.GROUP){
						String[] groupHql = toHql(result, params);
						from.append(" " + groupHql[0]);
						hqlTemp = "("+groupHql[1]+")";
					}else{
						String key = "p"+params.size();
						boolean join = condition.hasJoin();
						if(join){
							from.append(" inner join e." + name.split("\\.")[0] + " " + key);
							name = key + "." + name.split("\\.")[1];
						}else{
							name = "e." + name;
						}
						switch (operationType) {
						case EQ:
							if(result==null){
								hqlTemp = name + "is null";
							}else{
								hqlTemp = name + operationType.getKeyword() + ":"+key;
							}
							break;
						case NEQ:
							if(result==null){
								hqlTemp = name + "is not null";
							}else{
								hqlTemp = name + operationType.getKeyword() + ":"+key;
							}
							break;
						case IN:
							hqlTemp = name + operationType.getKeyword() + "(:"+key+")";
							break;
						default:
							hqlTemp = name + operationType.getKeyword() + ":"+key;
							break;
						}
						params.put(key, result);
					}
					if(!hasFirst&&relationType == RelationType.AND){
						hql.insert(0, hqlTemp);
						hasFirst = true;
					}else{
						hql.append(relationType.getKeyword() + hqlTemp);
					}
					
				}
			}
		}
		hqls[0] = from.toString();
		hqls[1] = hql.toString();
		return hqls;
	}

}
